<?php
/*
 * MiniMe - a minimalistic OStatus complient microblogging tool
 * Copyright (C) 2010, Tuomas Koski - koski.tuomas@gmail.com
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * @author     Tuomas Koski <koski.tuomas@gmail.com>
 * @copyright  Tuomas Koski
 * @license    http://www.gnu.org/licenses/lgpl.txt
 */
class Minime_Pubsubhubbub_Subscriber {
        
    private $callback;
    private $topic;
    private $lease_seconds;
    private $secret;
    private $verify_token;
    private $title;
    private $subid;
    
    const DEFAULT_LEASE_TIME = 86400;
    
    const ELEMENT_ROOT = "pubsubhubbub_subscriber";
    
    private function __construct() {
    }
    
    public function setSubID($subID) {
        if(empty($subID)) {
           throw new Exception("subID cannot be set empty!");
       }
       $this->subid = $subID;
    }
    
    public function getSubID() {
        return $this->subid;
    }
    
    public function setCallback($callback) {
       if(empty($callback)) {
           throw new Exception("Callback cannot be set empty!");
       }
       $this->callback = $callback;
    }
    
    public function getCallback() {
        return $this->callback;
    }
    
    public function setTopic($topic) {
       if(empty($topic)) {
           throw new Exception("Topic cannot be set empty!");
       }
       $this->topic = $topic;
    }
    
    public function setLeaseSeconds($lease_seconds) {
       if(empty($lease_seconds)) {
           throw new Exception("Lease Seconds cannot be set empty!");
       }
       $this->lease_seconds = $lease_seconds;
    }
    
    public function setSecret($secret) {
       if(empty($secret)) {
           throw new Exception("Secret cannot be set empty!");
       }
       $this->secret = $secret;
    }
    
    public function getSecret() {
        return $this->secret;
    }
    
    public function setVerifyToken($verify_token) {
       if(empty($verify_token)) {
           throw new Exception("Callback cannot be set empty!");
       }
       $this->verify_token = $verify_token;
    }
    
    public function setTitle($title) {
       if(empty($title)) {
           throw new Exception("Callback cannot be set empty!");
       }
       $this->title = $title;
    }
    
    public function asDOMElement(DOMDocument $dom) {
        $root = $dom->createElement(self::ELEMENT_ROOT);
        
        $root->setAttribute("id", $this->subid);
        
        $callback = $dom->createElement('callback', htmlspecialchars($this->callback, ENT_QUOTES, "UTF-8", false));
        $topic = $dom->createElement('topic', htmlspecialchars($this->topic, ENT_QUOTES, "UTF-8", false));
        $lease_seconds = $dom->createElement('lease_seconds', htmlspecialchars($this->lease_seconds, ENT_QUOTES, "UTF-8", false));
        $secret = $dom->createElement('secret', htmlspecialchars($this->secret, ENT_QUOTES, "UTF-8", false));
        $verify_token = $dom->createElement('verify_token', htmlspecialchars($this->verify_token, ENT_QUOTES, "UTF-8", false));
        $title = $dom->createElement('title', htmlspecialchars($this->title, ENT_QUOTES, "UTF-8", false));
        $subid = $dom->createElement('subid', htmlspecialchars($this->subid, ENT_QUOTES, "UTF-8", false));
        
        $root->appendChild($callback);
        $root->appendChild($topic);
        $root->appendChild($lease_seconds);
        $root->appendChild($secret);
        $root->appendChild($verify_token);
        $root->appendChild($title);
        $root->appendChild($subid);
        
        return $root;
    }
    
    public function asXml() {
        
        $doc = new DOMDocument('1.0', 'UTF-8');
        // we want a nice output
        $doc->formatOutput = true;

        $root = $this->asDOMElement($doc);
        $root = $doc->appendChild($root);
        
        return $doc->saveXML();
    }
    
    public static function buildFromArray(Array $array) {
        
        $sub = new Minime_Pubsubhubbub_Subscriber();
        $sub->setCallback($array['callback']);
        $sub->setTopic($array['topic']);
        $sub->setLeaseSeconds($array['lease_seconds']);
        $sub->setSecret($array['secret']);
        $sub->setVerifyToken($array['verify_token']);
        $sub->setTitle($array['title']);
        $sub->setSubID($array['subid']);
        
        return $sub;
    }
    
    public static function buildFromDOMElement(DOMElement $elm) {
        
        $sub = new Minime_Pubsubhubbub_Subscriber();
        $sub->setCallback($elm->getElementsByTagName('callback')->item(0)->nodeValue);
        $sub->setTopic($elm->getElementsByTagName('topic')->item(0)->nodeValue);
        $sub->setLeaseSeconds($elm->getElementsByTagName('lease_seconds')->item(0)->nodeValue);
        $sub->setSecret($elm->getElementsByTagName('secret')->item(0)->nodeValue);
        $sub->setVerifyToken($elm->getElementsByTagName('verify_token')->item(0)->nodeValue);
        $sub->setTitle($elm->getElementsByTagName('title')->item(0)->nodeValue);
        $sub->setSubID($elm->getElementsByTagName('subid')->item(0)->nodeValue);
        
        return $sub;
    }
    
    public static function buildFromRawXML($rawXML) {
        $dom = new DOMDocument();
        if(@$dom->loadXML($rawXML)) {
            return self::buildFromDom($dom);
        }
        throw new Exception("Invalid raw XML data provided!");
    }
    
    public static function buildFromDom(DOMDocument $dom) {
        
        $subscription_elm = $dom->getElementsByTagName(self::ELEMENT_ROOT)->item(0);
        if(!$subscription_elm) {
            throw new Exception("Invalid XML! No pubsubhubbub_subscription element found!");
        }
        
        return Minime_Pubsubhubbub_Subscriber::buildFromDOMElement($subscription_elm);
    }
    
    public static function calculateSubIdFromNode($node) {
        return md5($node);
    }
}